package controller.impl;

import java.util.Queue;

import controller.IController;

import sharedGameLogic.enums.BattleEvent;
import sharedNetwork.Connection;

import network.INetwork;
import network.NetworkFactory;
import network.NetworkID;
import network.ServerNetworkListener;

import model.IModelCreator;
import model.IServerModel;
import model.IServerNetwork;
import model.ServerModelFactory;

public class Controller implements ServerNetworkListener, IController {
	
	private IServerModel model;
	private IServerNetwork networkModel;
	private INetwork network;
	private int port = 6701;
	
	private Controller() {
		NetworkFactory networkFactory = new NetworkFactory();
		
		ServerModelFactory modelFactory = new ServerModelFactory();
		IModelCreator modelCreator = modelFactory.newInstance();
		
		model = modelCreator.getAsIServerModel();
		networkModel = modelCreator.getAsIServerNetwork();
		network = networkFactory.getNewNetwork(networkModel, port, this);
		network.start();
		model.addModelListener(network.getAsModelListener());
		System.out.println("Server running on port: " + port + ".");
	}
	
	/**
	 * 
	 * @return
	 */
	public static IController getNewInstance() {
		return new Controller();
	}

	@SuppressWarnings("unchecked")
	@Override
	public void networkMessageRecieved(Object obj, NetworkID id) {
		if (obj instanceof Queue<?>) {
			Queue<?> queue = (Queue<?>) obj;
			if (queue.peek() instanceof BattleEvent) {
				if (model.isGameReady()) {
					Queue<BattleEvent> actions = (Queue<BattleEvent>) queue;
					model.update(id, actions);
				}
			}
		} else if (obj instanceof Connection) {
			//TODO: Remove println
			System.out.println("WE HAVE A CONNECTION");
			if (!model.isGameReady()) {
				Connection connection = (Connection) obj;
				model.init(connection.getPlayer(), id);
			}
		}
	}

	@Override
	public void clientDisconnected(NetworkID id) {
		
	}
	
	@Override
	public void shutDown() {
		network.shutDown();
	}

	@Override
	public void clientAcceptedDisconnection(NetworkID id) {
		clientDisconnected(id);
	}

	@Override
	public void clientRequestedDisconnection(NetworkID id) {
		clientDisconnected(id);
	}
}
